from PySide2.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QDialog,
    QFrame, QListView, QListWidget, QListWidgetItem, QSplitter,
    QSizePolicy, QSpacerItem, QStatusBar, QStyledItemDelegate, QStyle,
    QTableView, QHeaderView, QApplication
)
from PySide2.QtCore import Qt, QModelIndex, Signal, QRect, QPropertyAnimation, QEasingCurve, QTimer, QEvent
from PySide2.QtGui import QIcon, QPixmap, QFont, QPainter, QColor, QPen, QBrush, QLinearGradient, QFontMetrics
from gglobal import logger
from ..models.calibration_function_model import CalibrationFunctionModel, DetectionItemModel
from .property_button import ScanButton, ConnectButton
from ..handlercore.networkscan_manager import NetworkScanManager
from ..handlercore.vehicle_connection_manager import VehicleConnectionManager
from ..handlercore.language_manager import LanguageManager
from ..handlercore.theme_manager import ThemeManager
from ..handlercore.signal_manager import create_signal_manager
from .calibration_action_window import CalibrationActionWindow
from .custom_combo_box import CustomComboBox
from .calibration_data_check import CalibrationDataChecker
from .calibration_button import CalibrationButtonManager
from .system_check_dialog import SystemCheckDialog
from ..handlercore.calibration_command_executor import CalibrationCommandExecutor


class CalibrationItemDelegate(QStyledItemDelegate):
    """
    标定功能项自定义委托
    负责绘制选中项的特殊样式效果，包括动画和视觉增强
    """
    
    def __init__(self, parent=None):
        super(CalibrationItemDelegate, self).__init__(parent)
        # 动画相关属性
        self._animation_progress = {}  # 存储每个项目的动画进度
        self._hover_items = set()  # 存储当前悬停的项目
        
    def paint(self, painter, option, index):
        """自定义绘制方法"""
        # 获取项目状态信息
        item_data = index.data(Qt.UserRole)
        is_selected = index.data(Qt.UserRole + 1)
        
        # 确保选中状态正确获取
        if is_selected is None:
            is_selected = False
        
        painter.save()
        
        # 设置抗锯齿
        painter.setRenderHint(QPainter.Antialiasing, True)
        
        # 获取绘制区域
        rect = option.rect
        
        # 获取动画进度，如果没有动画则使用1.0（完全显示）
        animation_progress = self.get_animation_progress(index)
        if animation_progress == 0.0:
            animation_progress = 1.0  # 确保即使没有动画也能正常显示
        
        # 绘制背景 - 优先绘制选中状态
        if is_selected:
            self._paint_selected_background(painter, rect, item_data, animation_progress)
        elif option.state & QStyle.State_MouseOver:
            self._paint_hover_background(painter, rect)
        
        # 绘制文本
        self._paint_text(painter, option, index, is_selected)
        
        # 绘制装饰（图标等）
        self._paint_decoration(painter, option, index)
        
        painter.restore()
    
    def start_selection_animation(self, index):
        """启动选中动画"""
        if not index.isValid():
            return
            
        # 创建动画对象
        animation = QPropertyAnimation(self, b"animationProgress")
        animation.setDuration(200)  # 200ms动画时长
        animation.setStartValue(0.0)
        animation.setEndValue(1.0)
        animation.setEasingCurve(QEasingCurve.OutCubic)
        
        # 存储动画进度
        item_key = f"{index.row()}_{index.column()}"
        self._animation_progress[item_key] = 0.0
        
        # 连接动画更新信号
        animation.valueChanged.connect(lambda value: self._update_animation_progress(item_key, value))
        animation.finished.connect(lambda: self._animation_finished(item_key))
        
        # 启动动画
        animation.start()
    
    def _update_animation_progress(self, item_key, progress):
        """更新动画进度"""
        self._animation_progress[item_key] = progress
        # 触发重绘
        if self.parent():
            self.parent().update()
    
    def _animation_finished(self, item_key):
        """动画完成回调"""
        if item_key in self._animation_progress:
            self._animation_progress[item_key] = 1.0
    
    def get_animation_progress(self, index):
        """获取指定项目的动画进度"""
        if not index.isValid():
            return 1.0
        item_key = f"{index.row()}_{index.column()}"
        return self._animation_progress.get(item_key, 1.0)
    
    def _paint_selected_background(self, painter, rect, item_data, animation_progress=1.0):
        """绘制选中状态的背景"""
        # 绘制阴影效果
        self._paint_shadow(painter, rect, animation_progress)
        
        # 创建主背景渐变 - 使用更明显的颜色
        gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft())
        
        # 使用更明显的蓝色背景，提高透明度
        base_alpha = int(120 * animation_progress)  # 47% 透明度（更明显）
        secondary_alpha = int(80 * animation_progress)  # 31% 透明度
        
        primary_color = QColor(42, 130, 228, base_alpha)
        secondary_color = QColor(42, 130, 228, secondary_alpha)
        
        gradient.setColorAt(0.0, primary_color)
        gradient.setColorAt(0.5, QColor(42, 130, 228, int(100 * animation_progress)))  # 中间色
        gradient.setColorAt(1.0, secondary_color)
        
        # 绘制圆角矩形背景
        painter.setBrush(QBrush(gradient))
        painter.setPen(Qt.NoPen)
        painter.drawRoundedRect(rect.adjusted(1, 0, -1, 0), 4, 4)  # 调整边距和圆角
        
        # 绘制左侧强调边框（圆角） - 根据动画进度调整
        border_alpha = int(255 * animation_progress)  # 100% 透明度（更明显）
        border_color = QColor(42, 130, 228, border_alpha)
        painter.setPen(QPen(border_color, 4, Qt.SolidLine, Qt.RoundCap))
        painter.drawLine(rect.left() + 2, rect.top() + 4, rect.left() + 2, rect.bottom() - 4)
        
        # 绘制内部高光效果 - 根据动画进度调整
        highlight_gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft())
        highlight_gradient.setColorAt(0.0, QColor(255, 255, 255, int(60 * animation_progress)))  # 顶部高光
        highlight_gradient.setColorAt(0.3, QColor(255, 255, 255, int(30 * animation_progress)))
        highlight_gradient.setColorAt(1.0, QColor(255, 255, 255, 0))   # 底部透明
        
        painter.setBrush(QBrush(highlight_gradient))
        painter.setPen(Qt.NoPen)
        painter.drawRoundedRect(rect.adjusted(2, 1, -2, -rect.height()//2), 3, 3)
        
        # 绘制细微的边框 - 根据动画进度调整
        border_light_alpha = int(180 * animation_progress)  # 70% 透明度（更明显）
        border_light = QColor(42, 130, 228, border_light_alpha)
        painter.setPen(QPen(border_light, 1))
        painter.setBrush(Qt.NoBrush)
        painter.drawRoundedRect(rect.adjusted(1, 0, -1, 0), 4, 4)
    
    def _paint_shadow(self, painter, rect, animation_progress=1.0):
        """绘制阴影效果"""
        # 创建阴影渐变 - 根据动画进度调整透明度
        shadow_gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft())
        shadow_gradient.setColorAt(0.0, QColor(0, 0, 0, int(20 * animation_progress)))
        shadow_gradient.setColorAt(1.0, QColor(0, 0, 0, int(40 * animation_progress)))
        
        # 绘制阴影（稍微偏移）
        shadow_rect = rect.adjusted(1, 2, 1, 2)
        painter.setBrush(QBrush(shadow_gradient))
        painter.setPen(Qt.NoPen)
        painter.drawRoundedRect(shadow_rect, 3, 3)
    
    def _paint_hover_background(self, painter, rect):
        """绘制悬停状态的背景"""
        # 创建悬停渐变效果
        hover_gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft())
        hover_gradient.setColorAt(0.0, QColor(42, 130, 228, 30))  # 12% 透明度
        hover_gradient.setColorAt(0.5, QColor(42, 130, 228, 20))  # 8% 透明度
        hover_gradient.setColorAt(1.0, QColor(42, 130, 228, 15))  # 6% 透明度
        
        # 绘制圆角悬停背景
        painter.setBrush(QBrush(hover_gradient))
        painter.setPen(Qt.NoPen)
        painter.drawRoundedRect(rect.adjusted(1, 0, -1, 0), 2, 2)
        
        # 绘制左侧细微的悬停指示线
        hover_border = QColor(42, 130, 228, 100)  # 40% 透明度
        painter.setPen(QPen(hover_border, 2, Qt.SolidLine, Qt.RoundCap))
        painter.drawLine(rect.left() + 1, rect.top() + 4, rect.left() + 1, rect.bottom() - 4)
    
    def _paint_text(self, painter, option, index, is_selected):
        """绘制文本"""
        text = index.data(Qt.DisplayRole)
        if not text:
            return
        
        # 设置文本颜色
        if is_selected:
            text_color = QColor(255, 255, 255)  # 白色文字
        else:
            text_color = option.palette.color(option.palette.Text)
        
        painter.setPen(text_color)
        
        # 设置字体 - 选中项使用粗体
        font = index.data(Qt.FontRole)
        if font:
            if is_selected:
                font.setBold(True)  # 选中项使用粗体
                font.setPointSize(font.pointSize() + 1)  # 稍微增大字体
            painter.setFont(font)
        else:
            # 如果没有字体信息，创建默认字体
            default_font = QFont()
            if is_selected:
                default_font.setBold(True)
                default_font.setPointSize(10)
            else:
                default_font.setPointSize(9)
            painter.setFont(default_font)
        
        # 计算文本区域（留出左侧边框空间）
        text_rect = option.rect.adjusted(12, 2, -4, -2)  # 增加左边距以避开边框
        
        # 绘制文本
        painter.drawText(text_rect, Qt.AlignLeft | Qt.AlignVCenter, text)
    
    def _paint_decoration(self, painter, option, index):
        """绘制装饰（图标等）"""
        icon = index.data(Qt.DecorationRole)
        if icon and not icon.isNull():
            # 计算图标位置
            icon_size = 16
            icon_rect = QRect(
                option.rect.right() - icon_size - 8,
                option.rect.top() + (option.rect.height() - icon_size) // 2,
                icon_size,
                icon_size
            )
            
            # 绘制图标
            icon.paint(painter, icon_rect)

class AdaptiveColumnWidthManager:
    """
    自适应列宽管理器
    负责动态计算和调整表格列宽，确保内容完整显示
    """
    
    def __init__(self, table_view: QTableView):
        """
        初始化自适应列宽管理器
        
        Args:
            table_view: 要管理的表格视图
        """
        self.table_view = table_view
        self.header = table_view.horizontalHeader()
        self.model = table_view.model()
        
        # 列宽配置
        self.min_column_width = 80   # 最小列宽
        self.max_column_width = 300  # 最大列宽
        self.padding = 20            # 内容边距
        self.header_padding = 30     # 表头额外边距
        
        # 延迟调整定时器，避免频繁调整
        self.adjust_timer = QTimer()
        self.adjust_timer.setSingleShot(True)
        self.adjust_timer.timeout.connect(self._perform_adjustment)
        self.adjust_delay = 100  # 100ms延迟
        
        # 连接信号
        self._connect_signals()
    
    def _connect_signals(self):
        """连接相关信号"""
        # 当模型数据变化时调整列宽
        if self.model:
            self.model.dataChanged.connect(self.schedule_adjustment)
            self.model.rowsInserted.connect(self.schedule_adjustment)
            self.model.rowsRemoved.connect(self.schedule_adjustment)
            self.model.modelReset.connect(self.schedule_adjustment)
        
        # 当表格大小变化时调整列宽
        self.table_view.resizeEvent = self._wrap_resize_event(self.table_view.resizeEvent)
    
    def _wrap_resize_event(self, original_resize_event):
        """包装原始的resize事件"""
        def wrapped_resize_event(event):
            original_resize_event(event)
            self.schedule_adjustment()
        return wrapped_resize_event
    
    def schedule_adjustment(self):
        """安排延迟调整，避免频繁调整"""
        self.adjust_timer.start(self.adjust_delay)
    
    def _perform_adjustment(self):
        """执行实际的列宽调整"""
        if not self.model or self.model.rowCount() == 0:
            return
        
        try:
            self.adjust_column_widths()
        except Exception as e:
            logger.error(f"调整列宽时出错: {e}")
    
    def calculate_content_width(self, column: int) -> int:
        """
        计算指定列的内容宽度
        
        Args:
            column: 列索引
            
        Returns:
            int: 计算出的内容宽度
        """
        if not self.model:
            return self.min_column_width
        
        max_width = 0
        font_metrics = QFontMetrics(self.table_view.font())
        
        # 计算表头宽度
        header_text = self.model.headerData(column, Qt.Horizontal, Qt.DisplayRole)
        if header_text:
            header_width = font_metrics.width(str(header_text)) + self.header_padding
            max_width = max(max_width, header_width)
        
        # 计算数据行宽度
        row_count = min(self.model.rowCount(), 100)  # 限制检查行数以提高性能
        for row in range(row_count):
            index = self.model.index(row, column)
            text = self.model.data(index, Qt.DisplayRole)
            if text:
                text_width = font_metrics.width(str(text)) + self.padding
                max_width = max(max_width, text_width)
        
        # 应用最小和最大宽度限制
        return max(self.min_column_width, min(max_width, self.max_column_width))
    
    def adjust_column_widths(self):
        """调整所有列的宽度"""
        if not self.model:
            return
        
        column_count = self.model.columnCount()
        if column_count == 0:
            return
        
        # 获取表格可用宽度
        available_width = self.table_view.viewport().width()
        if available_width <= 0:
            return
        
        # 检查是否启用等宽模式
        if hasattr(self, 'equal_width_mode') and self.equal_width_mode:
            # 等宽模式：所有列宽度相等（1:1比例）
            equal_width = available_width // column_count
            remaining_width = available_width % column_count
            
            for column in range(column_count):
                # 最后一列加上余数，确保完全填满
                if column == column_count - 1:
                    column_width = equal_width + remaining_width
                else:
                    column_width = equal_width
                
                # 确保不小于最小宽度
                column_width = max(column_width, self.min_column_width)
                self.header.resizeSection(column, column_width)
        else:
            # 原有的自适应宽度模式
            # 计算每列的理想宽度
            ideal_widths = []
            total_ideal_width = 0
            
            for column in range(column_count):
                ideal_width = self.calculate_content_width(column)
                ideal_widths.append(ideal_width)
                total_ideal_width += ideal_width
            
            # 如果理想宽度总和小于可用宽度，按比例扩展以填满容器
            if total_ideal_width < available_width:
                # 计算剩余空间
                remaining_width = available_width - total_ideal_width
                
                # 优先扩展第一列（检测项名称列），因为它通常内容更多
                if column_count > 0:
                    # 将大部分剩余空间分配给第一列
                    first_column_extra = int(remaining_width * 0.8)  # 80%给第一列
                    remaining_for_others = remaining_width - first_column_extra
                    
                    # 设置第一列宽度
                    first_column_width = ideal_widths[0] + first_column_extra
                    self.header.resizeSection(0, first_column_width)
                    
                    # 其余列平分剩余空间
                    if column_count > 1:
                        extra_per_column = remaining_for_others // (column_count - 1)
                        for column in range(1, column_count):
                            final_width = ideal_widths[column] + extra_per_column
                            self.header.resizeSection(column, final_width)
            else:
                # 如果理想宽度总和大于可用宽度，需要压缩以适应容器
                scale_factor = available_width / total_ideal_width
                total_assigned = 0
                
                for column in range(column_count):
                    if column == column_count - 1:
                        # 最后一列使用剩余宽度，确保完全填满
                        final_width = available_width - total_assigned
                    else:
                        scaled_width = int(ideal_widths[column] * scale_factor)
                        # 确保不小于最小宽度
                        final_width = max(scaled_width, self.min_column_width)
                        total_assigned += final_width
                    
                    self.header.resizeSection(column, final_width)
    
    def set_column_width_limits(self, min_width: int, max_width: int):
        """
        设置列宽限制
        
        Args:
            min_width: 最小列宽
            max_width: 最大列宽
        """
        self.min_column_width = max(50, min_width)  # 最小不能小于50
        self.max_column_width = max(self.min_column_width, max_width)
    
    def set_padding(self, content_padding: int, header_padding: int = None):
        """
        设置内容边距
        
        Args:
            content_padding: 内容边距
            header_padding: 表头边距，如果为None则使用content_padding + 10
        """
        self.padding = max(10, content_padding)
        self.header_padding = header_padding or (self.padding + 10)
    
    def force_adjustment(self):
        """强制立即调整列宽"""
        self.adjust_timer.stop()
        self._perform_adjustment()
    
    def ensure_full_width_coverage(self):
        """确保表格完全占满容器宽度"""
        if not self.model:
            return
        
        # 获取当前可用宽度
        available_width = self.table_view.viewport().width()
        if available_width <= 0:
            return
        
        # 获取当前所有列的总宽度
        current_total_width = 0
        column_count = self.model.columnCount()
        
        for column in range(column_count):
            current_total_width += self.header.sectionSize(column)
        
        # 如果当前总宽度小于可用宽度，调整最后一列以填满
        if current_total_width < available_width and column_count > 0:
            last_column = column_count - 1
            current_last_width = self.header.sectionSize(last_column)
            additional_width = available_width - current_total_width
            new_last_width = current_last_width + additional_width
            self.header.resizeSection(last_column, new_last_width)
    
    def set_equal_width_mode(self, enable: bool = True):
        """
        设置等宽模式（1:1列宽比例）
        
        Args:
            enable: 是否启用等宽模式
        """
        self.equal_width_mode = enable
        # 立即应用新的列宽设置
        self.force_adjustment()
    
    def set_responsive_mode(self, enable: bool = True):
        """
        设置响应式模式
        
        Args:
            enable: 是否启用响应式模式
        """
        if enable:
            # 连接窗口大小变化事件
            if hasattr(self.table_view, 'parent') and self.table_view.parent():
                parent = self.table_view.parent()
                while parent and not hasattr(parent, 'resizeEvent'):
                    parent = parent.parent()
                
                if parent:
                    original_resize = parent.resizeEvent
                    def responsive_resize(event):
                        original_resize(event)
                        # 延迟调整以确保布局完成
                        QTimer.singleShot(50, self.ensure_full_width_coverage)
                    parent.resizeEvent = responsive_resize


class FullCenterAlignDelegate(QStyledItemDelegate):
    """
    全表格居中对齐委托
    用于将表格所有单元格内容水平和垂直居中显示
    """
    
    def __init__(self, parent=None):
        super(FullCenterAlignDelegate, self).__init__(parent)
    
    def paint(self, painter, option, index):
        """重写绘制方法，实现完全居中对齐"""
        # 创建选项对象的副本，设置水平和垂直居中对齐
        from PySide2.QtWidgets import QStyleOptionViewItem
        new_option = QStyleOptionViewItem(option)
        new_option.displayAlignment = Qt.AlignCenter | Qt.AlignVCenter
        
        # 调用父类的绘制方法
        super(FullCenterAlignDelegate, self).paint(painter, new_option, index)
    
    def sizeHint(self, option, index):
        """提供尺寸提示，确保有足够的垂直空间进行居中"""
        size = super(FullCenterAlignDelegate, self).sizeHint(option, index)
        # 确保最小高度，提供更好的垂直居中效果
        size.setHeight(max(size.height(), 32))
        return size


class CenterAlignDelegate(QStyledItemDelegate):
    """
    居中对齐委托（保留向后兼容性）
    用于将表格单元格内容居中显示
    """
    
    def __init__(self, parent=None):
        super(CenterAlignDelegate, self).__init__(parent)
    
    def paint(self, painter, option, index):
        """重写绘制方法，实现居中对齐"""
        # 创建选项对象的副本，设置居中对齐
        from PySide2.QtWidgets import QStyleOptionViewItem
        new_option = QStyleOptionViewItem(option)
        new_option.displayAlignment = Qt.AlignCenter
        
        # 调用父类的绘制方法
        super(CenterAlignDelegate, self).paint(painter, new_option, index)


class CalibrationWidget(QWidget):
    """
    车辆标定界面控件类
    包含车辆连接、功能菜单和检测项显示
    """
    
    # 信号定义
    calibration_started = Signal(str)  # 标定开始信号，传递标定类型
    calibration_stopped = Signal()    # 标定停止信号
    
    def __init__(self, parent=None, language_manager=None):
        super(CalibrationWidget, self).__init__(parent)
        self.setObjectName("calibration_widget")
        
        # 初始化组件
        self.language_manager = language_manager or LanguageManager()
        self.theme_manager = ThemeManager()
        self._signal_manager = create_signal_manager("CalibrationWidget", self)
        
        # 初始化管理器
        self.network_scan_manager = NetworkScanManager(self)
        self.vehicle_connection_manager = VehicleConnectionManager(self)
        
        # 数据模型
        self.function_model = CalibrationFunctionModel(self)
        self.detection_model = DetectionItemModel(self)
        
        # 新增：数据检查器和按钮管理器
        self.data_checker = CalibrationDataChecker()
        self.button_manager = CalibrationButtonManager(self)
        
        # 自适应列宽管理器（稍后初始化）
        self.column_width_manager = None
        
        # 当前选中的标定项
        self.current_calibration_item = None

        # 初始化进度窗口
        self.progress_widget = None

        # 新增：标定动作窗口引用（避免被GC回收）
        self.calibration_action_window = None
        
        # 系统检测对话框
        self.system_check_dialog = None
        
        # 初始化UI
        self.init_ui()
        self.resize(1200, 600)
        self._current_calibration_item = None
        self._image_fit_mode = 'contain'
        
        # 连接信号
        self.connect_signals()
        self.setup_manager_connections()
        
        # 设置初始状态 - 检测项区域显示为空状态
        self.detection_model.clear_detection_data()
        
        logger.info("车辆标定界面初始化完成")
    
    def init_ui(self):
        """初始化用户界面 - 三区域弹性布局"""
        # 创建主布局
        main_layout = QVBoxLayout(self)
        main_layout.setContentsMargins(10, 10, 10, 10)
        main_layout.setSpacing(0)  # 减少间距以更好控制布局
        
        # ===== 顶部固定区域 =====
        top_widget = self.create_top_fixed_area()
        main_layout.addWidget(top_widget)
        
        # ===== 中间可拉伸区域 =====
        middle_widget = self.create_middle_stretchable_area()
        main_layout.addWidget(middle_widget, 1)  # stretch factor = 1，使其可拉伸
        
        # ===== 底部固定区域 =====
        bottom_widget = self.create_bottom_fixed_area()
        main_layout.addWidget(bottom_widget)
        
        # 注册多语言支持
        self.register_language_widgets()
    
    def create_top_fixed_area(self):
        """创建顶部固定区域 - 包含车辆连接控制"""
        top_widget = QWidget()
        top_widget.setObjectName("top_fixed_area")
        top_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        
        top_layout = QVBoxLayout(top_widget)
        top_layout.setContentsMargins(0, 0, 0, 10)
        top_layout.setSpacing(10)
        
        # 创建车辆连接区域
        self.create_vehicle_connection_area(top_layout)
        
        return top_widget
    
    def create_middle_stretchable_area(self):
        """创建中间可拉伸区域 - 包含标定内容"""
        middle_widget = QWidget()
        middle_widget.setObjectName("middle_stretchable_area")
        middle_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        
        middle_layout = QVBoxLayout(middle_widget)
        middle_layout.setContentsMargins(0, 0, 0, 0)
        middle_layout.setSpacing(10)
        
        # 创建水平分割器
        splitter = QSplitter(Qt.Horizontal)
        splitter.setChildrenCollapsible(False)
        splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        
        # 创建左侧功能菜单区域
        left_widget = self.create_left_menu_area()
        splitter.addWidget(left_widget)
        
        # 创建右侧详情区域
        right_widget = self.create_right_detail_area()
        splitter.addWidget(right_widget)
        
        splitter.setStretchFactor(0, 3)
        splitter.setStretchFactor(1, 10)
        
        middle_layout.addWidget(splitter)
        
        return middle_widget
    
    def create_bottom_fixed_area(self):
        """创建底部固定区域 - 包含状态栏"""
        bottom_widget = QWidget()
        bottom_widget.setObjectName("bottom_fixed_area")
        bottom_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        
        bottom_layout = QVBoxLayout(bottom_widget)
        bottom_layout.setContentsMargins(0, 10, 0, 0)
        bottom_layout.setSpacing(0)
        
        # 创建状态栏
        self.create_status_bar(bottom_layout)
        
        return bottom_widget
    
    def create_vehicle_connection_area(self, layout):
        """创建车辆连接区域"""
        # 创建网段控制区域
        self.create_network_area(layout)
        
        # 创建连接控制区域
        self.create_connection_area(layout)
        
        # 创建分隔线
        separator = QFrame()
        separator.setFrameShape(QFrame.HLine)
        separator.setFrameShadow(QFrame.Sunken)
        layout.addWidget(separator)
        
    def create_network_area(self, parent_layout):
        """创建网段控制区域"""
        # 网段控制布局
        network_layout = QHBoxLayout()
        network_layout.setSpacing(10)
        
        # 网段标签
        self.network_label = QLabel()
        self.network_label.setObjectName("network_label")
        network_layout.addWidget(self.network_label)
        
        # 网段输入框列表
        current_theme = self.theme_manager.get_current_theme_name()
        self.network_combo = CustomComboBox(theme=current_theme)
        self.network_combo.setEditable(True)
        self.network_combo.setMinimumWidth(200)
        
        # 网段输入校验已移至NetworkScanManager
        network_layout.addWidget(self.network_combo)
        
        # 本机网段按钮
        self.local_network_button = ConnectButton()
        self.local_network_button.setObjectName("local_network_button")
        self.local_network_button.setMinimumSize(100, 32)
        network_layout.addWidget(self.local_network_button)
        
        # 扫描车辆按钮
        self.scan_button = ScanButton()
        self.scan_button.setObjectName("scan_button")
        self.scan_button.setMinimumSize(80, 32)
        network_layout.addWidget(self.scan_button)
        
        # 添加弹性空间
        network_layout.addStretch()
        
        parent_layout.addLayout(network_layout)
        
    def create_connection_area(self, parent_layout):
        """创建连接控制区域"""
        # 连接控制布局
        connection_layout = QHBoxLayout()
        connection_layout.setSpacing(10)
        
        # 车辆IP标签
        self.ip_label = QLabel()
        self.ip_label.setObjectName("vehicle_ip_label")
        connection_layout.addWidget(self.ip_label)
        
        # IP列表下拉框
        current_theme = self.theme_manager.get_current_theme_name()
        self.ip_combo = CustomComboBox(theme=current_theme)
        self.ip_combo.setEditable(True)
        self.ip_combo.setMinimumWidth(355)
        
        # IP输入校验已移至NetworkScanManager
        connection_layout.addWidget(self.ip_combo)
        
        # 连接按钮
        self.connect_button = ConnectButton()
        self.connect_button.setObjectName("connect_button")
        self.connect_button.setMinimumSize(80, 32)
        connection_layout.addWidget(self.connect_button)
        
        # 添加弹性空间
        connection_layout.addStretch()
        
        parent_layout.addLayout(connection_layout)
        
    def create_status_bar(self, parent_layout):
        """创建状态栏"""
        self.status_bar = QStatusBar()
        self.status_bar.setObjectName("calibration_status_bar")
        # 设置初始状态
        ready_text = self.language_manager.get_constant('status_ready')
        self.status_bar.showMessage(ready_text)
        parent_layout.addWidget(self.status_bar)
    
    def create_left_menu_area(self):
        """创建左侧功能菜单区域"""
        # 创建左侧容器
        left_widget = QWidget()
        left_layout = QVBoxLayout(left_widget)
        left_layout.setContentsMargins(5, 5, 5, 5)
        left_layout.setSpacing(5)
        
        # 创建标定菜单标题
        self.menu_title_label = QLabel("标定菜单")
        self.menu_title_label.setObjectName("calibration_menu_label")
        self.menu_title_label.setFont(QFont("Arial", 12, QFont.Bold))
        self.menu_title_label.setAlignment(Qt.AlignCenter)
        left_layout.addWidget(self.menu_title_label)
        
        # 创建功能菜单列表视图
        self.menu_list_view = QListView()
        self.menu_list_view.setObjectName("calibration_menu_list")
        self.menu_list_view.setModel(self.function_model)
        self.menu_list_view.setAlternatingRowColors(False)  # 禁用交替行颜色，使用自定义样式
        self.menu_list_view.setSelectionMode(QListView.SingleSelection)
        
        # 设置自定义委托以实现特殊的选中样式效果
        self.menu_item_delegate = CalibrationItemDelegate(self)
        self.menu_list_view.setItemDelegate(self.menu_item_delegate)
        
        # 确保选中状态样式正确应用
        self.menu_list_view.setFocusPolicy(Qt.StrongFocus)
        self.menu_list_view.setMouseTracking(True)  # 启用鼠标跟踪以支持悬停效果
        
        # 设置项目高度以提供更好的视觉效果
        self.menu_list_view.setUniformItemSizes(True)
        
        # 样式已在QSS文件中定义，通过objectName进行管理
        
        left_layout.addWidget(self.menu_list_view)
        
        return left_widget
    
    def create_right_detail_area(self):
        right_splitter = QSplitter(Qt.Horizontal)
        right_splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        right_splitter.setChildrenCollapsible(False)

        left_widget = QWidget()
        left_layout = QVBoxLayout(left_widget)
        left_layout.setContentsMargins(0, 0, 0, 0)
        left_layout.setSpacing(10)

        self.create_hint_area(left_layout)

        detection_widget = self.create_detection_area_with_scroll()
        left_layout.addWidget(detection_widget, 1)

        self.create_action_buttons_area(left_layout)

        right_splitter.addWidget(left_widget)

        self.right_image_label = QLabel()
        self.right_image_label.setObjectName("calibration_right_image")
        self.right_image_label.setAlignment(Qt.AlignCenter)
        self.right_image_label.setMinimumWidth(280)
        self.right_image_label.setMinimumHeight(0)
        self.right_image_label.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.right_image_label.hide()
        try:
            self.right_image_label.resizeEvent = self._wrap_image_resize_event(self.right_image_label.resizeEvent)
        except Exception:
            pass
        right_splitter.addWidget(self.right_image_label)
        #左侧检测项等布局与右侧图片比例1：1
        right_splitter.setStretchFactor(0, 1)
        right_splitter.setStretchFactor(1, 1)
        try:
            right_splitter.setSizes([500, 500])
        except Exception:
            pass

        return right_splitter
    
    def create_hint_area(self, layout):
        """创建提示区域"""
        # 创建提示框架
        self.hint_frame = QFrame()
        self.hint_frame.setFrameStyle(QFrame.StyledPanel)
        self.hint_frame.setMinimumHeight(60)  # 设置最小高度而非固定高度
        self.hint_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)  # 高度自适应
        
        hint_layout = QHBoxLayout(self.hint_frame)
        hint_layout.setContentsMargins(15, 12, 15, 12)  # 增加内边距
        hint_layout.setSpacing(10)  # 图标与文本间距10px
        
        # 提示图标 - 使用Qt资源系统加载SVG图标
        self.hint_icon_label = QLabel()
        # 使用Qt资源路径加载图标
        hint_pixmap = QPixmap(":/icon/hint.svg")
        if not hint_pixmap.isNull():
            # 缩放图标到合适大小
            scaled_pixmap = hint_pixmap.scaled(32, 32, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            self.hint_icon_label.setPixmap(scaled_pixmap)
        else:
            # 如果SVG加载失败，使用备用图标
            self.hint_icon_label.setText("ℹ️")
            self.hint_icon_label.setFont(QFont("Arial", 20))
        
        self.hint_icon_label.setFixedSize(32, 32)
        self.hint_icon_label.setAlignment(Qt.AlignCenter)
        self.hint_icon_label.setContentsMargins(0, 0, 10, 0)  # 右侧额外间距
        hint_layout.addWidget(self.hint_icon_label)

        # 使提示图标可点击：安装事件过滤器并修改鼠标光标
        try:
            self.hint_icon_label.setCursor(Qt.PointingHandCursor)
            self.hint_icon_label.installEventFilter(self)
        except Exception as e:
            logger.warning(f"[CalibrationWidget] 安装提示图标事件过滤器失败: {e}")
        
        # 标定场景提示文字
        self.hint_text_label = QLabel("请选择标定项目以查看详细说明")
        self.hint_text_label.setObjectName("calibration_hint_label")
        self.hint_text_label.setWordWrap(True)  # 启用自动换行
        self.hint_text_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.hint_text_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)  # 文本区域自适应
        hint_layout.addWidget(self.hint_text_label)

        
        
        layout.addWidget(self.hint_frame)
        
        # 初始调用高度自适应
        self.adjust_hint_area_height()

    def eventFilter(self, obj, event):
        """事件过滤器：处理提示图标点击事件"""
        try:
            if obj is getattr(self, 'hint_icon_label', None) and event and event.type() == QEvent.MouseButtonPress:
                self._on_hint_icon_clicked()
                # 返回True表示事件已处理
                return True
        except Exception as e:
            logger.warning(f"[CalibrationWidget] 处理提示图标点击事件失败: {e}")
        # 未处理的事件，交由父类处理
        return super(CalibrationWidget, self).eventFilter(obj, event)

    def _on_hint_icon_clicked(self):
        """提示图标点击：根据当前标定项显示对应图片"""
        item_key = getattr(self, 'current_calibration_item', None)
        if not item_key:
            logger.info("[CalibrationWidget] 当前未选择标定项，忽略提示图标点击")
            return
        self._show_hint_image_for_item(item_key)

    def _show_hint_image_for_item(self, item_key: str):
        """显示标定提示图片弹窗（根据标定项键）"""
        try:
            # 映射标定项到图片资源路径
            image_map = {
                "calibration_menu_laser_yaw": ":/calibration/calibration_menu_laser_yaw.png",
                "calibration_menu_laser_joint": ":/calibration/calibration_menu_laser_joint.png",
                "calibration_menu_mid360": ":/calibration/calibration_menu_mid360.png",
                "calibration_menu_fork_camera_sub1": ":/calibration/calibration_menu_fork_camera_sub1.png",
                "calibration_menu_recognition_camera_sub1": ":/calibration/calibration_menu_recognition_camera_sub1.png",
                "calibration_menu_recognition_camera_sub2": ":/calibration/calibration_menu_recognition_camera_sub2.png",
            }

            img_path = image_map.get(item_key)
            if not img_path:
                logger.info(f"[CalibrationWidget] 标定项 {item_key} 未提供提示图片")
                return

            pix = QPixmap(img_path)
            if pix.isNull():
                logger.warning(f"[CalibrationWidget] 提示图片资源加载失败: {img_path}")
                return

            # 限制最大显示尺寸并进行平滑缩放
            max_w, max_h = 800, 600
            scaled = pix.scaled(max_w, max_h, Qt.KeepAspectRatio, Qt.SmoothTransformation)

            # 创建弹窗对话框显示图片
            dlg = QDialog(self)
            dlg.setModal(True)
            title = self.language_manager.get_text("calibration_scenario_hint", "标定场景提示")
            dlg.setWindowTitle(title)
            vbox = QVBoxLayout(dlg)
            img_label = QLabel(dlg)
            img_label.setAlignment(Qt.AlignCenter)
            img_label.setPixmap(scaled)
            vbox.addWidget(img_label)

            # 添加关闭按钮
            btn = QPushButton(self.language_manager.get_text("ok_button", "确定"), dlg)
            btn.clicked.connect(dlg.accept)
            btn.setFixedWidth(100)
            btn.setCursor(Qt.PointingHandCursor)
            vbox.addWidget(btn, alignment=Qt.AlignCenter)

            # 调整对话框大小
            dlg.resize(min(scaled.width() + 40, max_w + 40), min(scaled.height() + 80, max_h + 80))
            dlg.exec_()
        except Exception as e:
            logger.exception(f"[CalibrationWidget] 显示提示图片失败: {e}")
    
    def adjust_hint_area_height(self):
        """根据文本内容调整提示区域高度"""
        if hasattr(self, 'hint_text_label') and hasattr(self, 'hint_frame'):
            # 计算文本所需的高度
            font_metrics = self.hint_text_label.fontMetrics()
            text_rect = font_metrics.boundingRect(
                0, 0, self.hint_text_label.width() - 20,  # 减去内边距
                0, Qt.TextWordWrap, self.hint_text_label.text()
            )
            
            # 计算所需高度：文本高度 + 内边距 + 一些额外空间
            required_height = max(60, text_rect.height() + 30)  # 最小60px
            
            # 设置框架高度
            self.hint_frame.setMinimumHeight(required_height)
            self.hint_frame.setMaximumHeight(required_height + 20)  # 允许一些弹性
    
    def create_detection_area(self, layout):
        """创建检测项区域"""
        
        # 创建检测项表格视图
        self.detection_table_view = QTableView()
        self.detection_table_view.setObjectName("detection_table_view")
        self.detection_table_view.setAlternatingRowColors(True)
        self.detection_table_view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.detection_table_view.setSelectionBehavior(QTableView.SelectRows)
        self.detection_table_view.setSelectionMode(QTableView.SingleSelection)
        self.detection_table_view.verticalHeader().setVisible(False)  # 隐藏行号
        self.detection_table_view.setShowGrid(False)  # 隐藏网格线
        
        # 连接模型到视图
        self.detection_table_view.setModel(self.detection_model)
        
        # 设置列宽自适应
        header = self.detection_table_view.horizontalHeader()
        header.setStretchLastSection(True)  # 最后一列拉伸填充
        header.setSectionResizeMode(0, QHeaderView.Stretch)  # 第一列拉伸
        header.setSectionResizeMode(1, QHeaderView.ResizeToContents)  # 第二列根据内容调整
        
        # 设置状态列（第二列）居中对齐
        self.detection_table_view.setItemDelegateForColumn(1, CenterAlignDelegate(self))
        
        layout.addWidget(self.detection_table_view)
    
    def create_detection_area_with_scroll(self):
        """创建支持滚动的检测项区域"""
        # 创建检测项容器
        detection_widget = QWidget()
        detection_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        detection_layout = QVBoxLayout(detection_widget)
        detection_layout.setContentsMargins(0, 0, 0, 0)  # 移除边距以最大化表格宽度
        detection_layout.setSpacing(0)  # 移除间距以最大化表格宽度
        

        
        # 创建检测项表格视图（支持滚动）
        self.detection_table_view = QTableView()
        self.detection_table_view.setObjectName("detection_table_view")
        self.detection_table_view.setAlternatingRowColors(True)
        self.detection_table_view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.detection_table_view.setSelectionBehavior(QTableView.SelectRows)
        self.detection_table_view.setSelectionMode(QTableView.SingleSelection)
        self.detection_table_view.verticalHeader().setVisible(False)  # 隐藏行号
        self.detection_table_view.setShowGrid(False)  # 隐藏网格线
        
        # 确保滚动条在需要时显示
        self.detection_table_view.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.detection_table_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        
        # 优化表格边框和边距设置，确保完全占满容器宽度
        self.detection_table_view.setFrameStyle(QFrame.NoFrame)  # 移除边框
        self.detection_table_view.setContentsMargins(0, 0, 0, 0)  # 移除内容边距
        self.detection_table_view.setLineWidth(0)  # 移除线宽
        self.detection_table_view.setMidLineWidth(0)  # 移除中线宽度
        
        # 连接模型到视图
        self.detection_table_view.setModel(self.detection_model)
        
        # 初始化自适应列宽管理器
        self.column_width_manager = AdaptiveColumnWidthManager(self.detection_table_view)
        
        # 设置列宽限制和边距
        self.column_width_manager.set_column_width_limits(100, 400)  # 最小100px，最大400px（增加最大宽度）
        self.column_width_manager.set_padding(15, 25)  # 内容边距15px，表头边距25px
        
        # 启用等宽模式（1:1列宽比例）
        self.column_width_manager.set_equal_width_mode(True)
        
        # 启用响应式模式，确保表格完全占满容器宽度
        self.column_width_manager.set_responsive_mode(True)
        
        # 设置表头不可手动调整（由自适应管理器控制）
        header = self.detection_table_view.horizontalHeader()
        header.setSectionResizeMode(QHeaderView.Fixed)
        
        # 设置表头居中对齐
        header.setDefaultAlignment(Qt.AlignCenter)
        
        # 为所有列设置全表格居中对齐委托
        self.full_center_delegate = FullCenterAlignDelegate(self)
        self.detection_table_view.setItemDelegate(self.full_center_delegate)
        
        detection_layout.addWidget(self.detection_table_view)
        
        return detection_widget
    
    def create_action_buttons_area(self, layout):
        """创建操作按钮区域"""
        # 创建按钮容器
        self.button_container = QWidget()
        self.button_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        
        # 创建按钮布局
        self.button_layout = QHBoxLayout(self.button_container)
        self.button_layout.setContentsMargins(0, 0, 0, 0)
        self.button_layout.setSpacing(10)
        
        # 添加弹性空间
        self.button_layout.addStretch()
        
        # 初始状态：显示提示信息
        self.no_selection_label = QLabel("请选择标定项目")
        self.no_selection_label.setObjectName("no_selection_label")
        self.no_selection_label.setAlignment(Qt.AlignCenter)
        self.no_selection_label.setStyleSheet("color: #888888; font-style: italic;")
        self.button_layout.addWidget(self.no_selection_label)
        
        self.button_layout.addStretch()
        
        layout.addWidget(self.button_container)
    
    def connect_signals(self):
        """连接信号槽"""
        # 连接菜单选择信号
        self.menu_list_view.clicked.connect(self.on_menu_item_clicked)
        
        self._signal_manager.register_connection("cal_req", self.button_manager.calibration_requested, self.on_calibration_requested, Qt.QueuedConnection)
        self._signal_manager.connect_signal("cal_req")
        
        # 连接模型信号
        self.function_model.item_selected.connect(self.on_calibration_item_selected)
        
        # 设置管理器的UI组件
        self.network_scan_manager.set_ui_components(
            self.network_combo, self.ip_combo, 
            self.scan_button, self.local_network_button
        )
        
        # 连接本地网段更新信号
        self.network_scan_manager.local_networks_updated.connect(self.network_scan_manager._on_local_networks_updated)
        
        self.vehicle_connection_manager.set_ui_components(
            self.connect_button, self.status_bar
        )
        
        logger.info("信号连接设置完成")
        
    def setup_manager_connections(self):
        """设置管理器信号连接"""
        
        # 车辆连接管理器信号连接 - 只连接核心管理信号
        self.vehicle_connection_manager.connection_status_changed.connect(self.on_connection_status_changed)
        self.vehicle_connection_manager.command_output.connect(self.on_command_output)
        
        logger.info("管理器信号连接设置完成")
    
    def register_language_widgets(self):
        """注册多语言控件"""
        if self.language_manager:
            # 注册网络扫描区域
            self.language_manager.register_widget(self.network_label, "network_label")
            self.language_manager.register_widget(self.local_network_button, "local_network_button")
            self.language_manager.register_widget(self.scan_button, "scan_button")
            
            # 注册车辆连接区域
            self.language_manager.register_widget(self.ip_label, "vehicle_ip_label")
            self.language_manager.register_widget(self.connect_button, "connect_button")
            
            # 注册菜单区域
            self.language_manager.register_widget(self.menu_title_label, "calibration_menu_title")
            
            # 注册右侧区域
            # 注意：按钮现在由CalibrationButtonManager动态管理，不需要在这里注册
            
            # 连接语言切换信号以调整列宽
            self.language_manager.language_changed.connect(self._on_language_changed)
    
    def _on_language_changed(self, language_data):
        """语言切换时的处理"""
        # 如果当前有选中的标定项，重新更新显示以应用新的翻译
        if self.current_calibration_item:
            self.update_detection_items_for_calibration(self.current_calibration_item)
        
        # 强制调整列宽以适应新的语言文本
        if self.column_width_manager:
            # 延迟调整，确保文本已经更新
            QTimer.singleShot(100, self.column_width_manager.force_adjustment)
            # 再次确保完全占满宽度
            QTimer.singleShot(200, self.column_width_manager.ensure_full_width_coverage)
    
    def on_menu_item_clicked(self, index: QModelIndex):
        """菜单项点击事件处理"""
        if not index.isValid():
            return
        
        # 触发选中动画
        self.menu_item_delegate.start_selection_animation(index)
        
        # 处理菜单项点击
        self.function_model.handle_item_click(index)
    
    def on_calibration_item_selected(self, item_name: str, can_start_calibration: bool):
        """标定项选择事件处理 - 增强调试日志"""
        logger.info(f"[CalibrationWidget] 选择标定项: {item_name}, 可以开始标定: {can_start_calibration}")
        
        # 如果可以开始标定，更新右侧显示
        if can_start_calibration:
            logger.info(f"[CalibrationWidget] 设置当前标定项: {self.current_calibration_item} -> {item_name}")
            self.current_calibration_item = item_name
            self.update_right_panel(item_name)
            # 更新检测项和按钮
            logger.info(f"[CalibrationWidget] 更新检测项和按钮: {item_name}")
            self.update_detection_items_for_calibration(item_name)
        else:
            # 选择主项时清空右侧显示
            logger.info(f"[CalibrationWidget] 清空当前标定项: {self.current_calibration_item} -> None")
            self.current_calibration_item = None
            self.detection_model.clear_detection_data()
            self._show_no_selection_state()
    
    def update_right_panel(self, calibration_item: str):
        """更新右侧面板显示"""
        # 更新提示文字
        hint_text = self.get_hint_text_for_item(calibration_item)
        self.hint_text_label.setText(hint_text)
        
        # 手动调用高度自适应（因为setText可能不会触发textChanged信号）
        self.adjust_hint_area_height()
        
        # 更新检测项
        self.update_detection_items_for_calibration(calibration_item)

        self._current_calibration_item = calibration_item
        self._update_right_image(calibration_item)
    
    def get_hint_text_for_item(self, item_key: str) -> str:
        """获取标定项的提示文字"""
        # 使用翻译键映射到提示文本键
        # 新增：为子项定义独立的提示键，避免与主项共用导致提示不匹配
        hint_key_map = {
            "calibration_menu_laser_yaw": "calibration_hint_laser_yaw",
            "calibration_menu_laser_joint": "calibration_hint_laser_joint", 
            "calibration_menu_mid360": "calibration_hint_mid360",
            "calibration_menu_fork_camera": "calibration_hint_fork_camera",
            "calibration_menu_fork_camera_sub1": "calibration_hint_fork_camera_sub1",
            "calibration_menu_recognition_camera": "calibration_hint_recognition_camera",
            "calibration_menu_recognition_camera_sub1": "calibration_hint_recognition_camera_sub1",
            "calibration_menu_recognition_camera_sub2": "calibration_hint_recognition_camera_sub2"
        }
        
        # 获取对应的提示文本键
        hint_key = hint_key_map.get(item_key, "calibration_hint_default")
        
        # 返回翻译后的提示文本
        return self.language_manager.get_text(hint_key, "请选择标定项目以查看详细说明")

    def _get_calibration_image_path(self, item_key: str) -> str:
        """根据标定项获取图片资源路径"""
        image_map = {
            "calibration_menu_laser_yaw": ":/calibration/calibration_menu_laser_yaw.png",
            "calibration_menu_laser_joint": ":/calibration/calibration_menu_laser_joint.png",
            "calibration_menu_mid360": ":/calibration/calibration_menu_mid360.png",
            "calibration_menu_fork_camera_sub1": ":/calibration/calibration_menu_fork_camera_sub1.png",
            "calibration_menu_recognition_camera_sub1": ":/calibration/calibration_menu_recognition_camera_sub1.png",
            "calibration_menu_recognition_camera_sub2": ":/calibration/calibration_menu_recognition_camera_sub2.png",
        }
        return image_map.get(item_key, "")

    def _update_right_image(self, item_key: str) -> None:
        try:
            img_path = self._get_calibration_image_path(item_key)
            if not img_path:
                self.right_image_label.clear()
                self.right_image_label.hide()
                return
            pix = QPixmap(img_path)
            if pix.isNull():
                self.right_image_label.clear()
                self.right_image_label.hide()
                return
            rect = self.right_image_label.contentsRect()
            target_w = max(rect.width(), self.right_image_label.minimumWidth())
            target_h = max(rect.height(), 1)
            transform = Qt.KeepAspectRatio if getattr(self, '_image_fit_mode', 'contain') == 'contain' else Qt.KeepAspectRatioByExpanding
            scaled = pix.scaled(target_w, target_h, transform, Qt.SmoothTransformation)
            self.right_image_label.setPixmap(scaled)
            self.right_image_label.show()
        except Exception:
            pass

    def _wrap_image_resize_event(self, original_resize_event):
        def wrapped_resize_event(event):
            try:
                original_resize_event(event)
            except Exception:
                pass
            try:
                if getattr(self, "_current_calibration_item", None):
                    self._update_right_image(self._current_calibration_item)
            except Exception:
                pass
        return wrapped_resize_event
    

    
    def update_detection_items_for_calibration(self, calibration_item_key: str):
        """根据标定项更新检测项显示"""
        # 刷新标定数据
        self.data_checker.refresh_calibration_data()
        
        # 获取该标定项所需的检测项（内部键）
        required_internal_items = self.data_checker.calibration_requirements.get(calibration_item_key, [])
        
        if not required_internal_items:
            # 如果没有找到对应的检测项，清空显示
            self.detection_model.clear_detection_data()
            logger.warning(f"未找到标定项 {calibration_item_key} 的检测要求")
            return
        
        # 获取翻译后的检测项名称
        translated_items = [self.data_checker.get_translated_data_name(item) for item in required_internal_items]
        
        # 获取检测项状态（使用内部键检查，但用翻译名称作为键）
        status_dict = {}
        for i, internal_item in enumerate(required_internal_items):
            translated_name = translated_items[i]
            status_dict[translated_name] = self.data_checker.check_data_validity(internal_item)
        
        # 更新检测项模型（使用翻译后的名称）
        self.detection_model.set_detection_data_for_calibration(translated_items, status_dict)
        
        # 强制调整列宽以适应新内容
        if self.column_width_manager:
            self.column_width_manager.force_adjustment()
            # 确保表格完全占满容器宽度
            QTimer.singleShot(50, self.column_width_manager.ensure_full_width_coverage)
        
        # 更新按钮状态（使用翻译后的状态字典）
        self._update_calibration_buttons(calibration_item_key, status_dict)
        
        logger.debug(f"更新标定项 {calibration_item_key} 的检测数据: {status_dict}")
    
    def set_table_column_mode(self, equal_width: bool = True):
        """
        设置表格列宽模式
        
        Args:
            equal_width: True为等宽模式（1:1比例），False为自适应模式
        """
        if self.column_width_manager:
            self.column_width_manager.set_equal_width_mode(equal_width)
            logger.info(f"表格列宽模式已切换为: {'等宽模式(1:1)' if equal_width else '自适应模式'}")
    
    def _update_calibration_buttons(self, calibration_item_key: str, status_dict: dict):
        """更新标定按钮状态 - 增强调试日志"""
        logger.info(f"[CalibrationWidget] 开始更新标定按钮状态: {calibration_item_key}")
        logger.info(f"[CalibrationWidget] 检测状态数据: {status_dict}")
        
        # 检查是否应该全局禁用
        global_disable, failed_conditions = self.data_checker.should_disable_all_calibration()
        logger.info(f"[CalibrationWidget] 全局禁用状态: {global_disable}, 失败条件: {failed_conditions}")
        
        # 清除旧的按钮
        self._clear_button_area()
        logger.debug("[CalibrationWidget] 已清除旧的按钮区域")
        
        # 创建新的按钮
        button_widget = self.button_manager.create_button_widget(calibration_item_key)
        if button_widget:
            self.button_layout.addWidget(button_widget)
            logger.info(f"[CalibrationWidget] 已创建按钮控件: {calibration_item_key}")
            
            # 更新按钮状态
            logger.info(f"[CalibrationWidget] 调用按钮管理器更新状态: calibration_item={calibration_item_key}, status={status_dict}, global_disable={global_disable}")
            self.button_manager.update_button_states(calibration_item_key, status_dict, global_disable)
            logger.info("[CalibrationWidget] 按钮状态更新完成")
        else:
            # 如果没有对应的按钮配置，显示提示信息
            logger.warning(f"[CalibrationWidget] 没有找到标定项 {calibration_item_key} 的按钮配置")
            no_button_label = QLabel("该标定项暂不支持")
            no_button_label.setAlignment(Qt.AlignCenter)
            no_button_label.setStyleSheet("color: #888888; font-style: italic;")
            self.button_layout.addWidget(no_button_label)
    
    def _clear_button_area(self):
        """清空按钮区域"""
        # 移除所有子控件
        while self.button_layout.count() > 0:
            item = self.button_layout.takeAt(0)
            if item.widget():
                item.widget().deleteLater()
            elif item.spacerItem():
                # 删除弹性空间项
                del item
        
        # 重新添加弹性空间
        self.button_layout.addStretch()
    
    def _show_no_selection_state(self):
        """显示未选择标定项的状态"""
        self._clear_button_area()
        try:
            if hasattr(self, "right_image_label"):
                self.right_image_label.clear()
                self.right_image_label.hide()
        except Exception:
            pass
        
        # 显示提示信息
        no_selection_label = QLabel("请选择标定项目")
        no_selection_label.setAlignment(Qt.AlignCenter)
        no_selection_label.setStyleSheet("color: #888888; font-style: italic;")
        self.button_layout.addWidget(no_selection_label)
        
        self.button_layout.addStretch()
    

    
    def on_connection_status_changed(self, connected: bool, message: str):
        """车辆连接状态变化处理 - 优化后的流程控制"""
        from datetime import datetime
        logger.info(f"[CalibrationWidget] 车辆连接状态变化: connected={connected}, message={message}")
        logger.info(f"[CalibrationWidget] 当前时间戳: {datetime.now().strftime('%H:%M:%S.%f')[:-3]}")
        
        # 取消任何待处理的检测窗口打开任务
        self._cancel_pending_system_check()
        
        if connected:
            logger.info("[CalibrationWidget] 连接成功，开始状态确认流程")
            # 启动连接状态确认流程，而不是直接打开检测窗口
            self._start_connection_verification()
        else:
            logger.info("[CalibrationWidget] 连接断开，清理相关状态")
            self._handle_connection_lost()
        
        # 更新标定按钮状态
        self._update_calibration_buttons_state()
    
    def on_command_output(self, output: str):
        """命令输出处理"""
        logger.info(f"车辆连接命令输出: {output}")
        # 可以在这里显示连接过程的详细信息
        # 如果标定动作窗口已打开，通过信号安全追加到日志视图
        try:
            if self.calibration_action_window:
                self.calibration_action_window.append_log_safe(output)
        except Exception as exc:
            logger.exception(f"转发命令输出到标定动作窗口失败: {exc}")
        
    def on_calibration_requested(self, calibration_type: str, calibration_key: str):
        """处理标定请求
        中文注释：统一信号管理后，个别环境下首参可能为空字符串；
        这里进行健壮性兜底，优先使用信号参数，若为空则回退到当前选中项。
        """
        # 中文注释：兜底修正标定类型（防止信号参数丢失）
        if not calibration_type:
            try:
                fallback_type = getattr(self, "current_calibration_item", None)
            except Exception:
                fallback_type = None
            if fallback_type:
                logger.warning(
                    f"[CalibrationWidget] 信号calibration_type为空，使用当前选中项回退: {fallback_type}"
                )
                calibration_type = fallback_type
            else:
                logger.error(
                    "[CalibrationWidget] 无法确定标定类型（信号与当前选中项均为空），忽略此次请求"
                )
                return

        # 中文注释：规范化标定键（仅允许 single/left/right，默认回退single）
        if calibration_key not in {"single", "left", "right"}:
            logger.warning(
                f"[CalibrationWidget] 非法的标定键: {calibration_key}，回退为 single"
            )
            calibration_key = "single"

        logger.info(f"收到标定请求: {calibration_type} for {calibration_key}")      
        # 检查车辆连接状态
        if not self.vehicle_connection_manager.is_connected():
            logger.warning("车辆未连接，无法开始标定")
            # 这里可以显示一个提示对话框
            return
        
        # 再次检查数据有效性
        # 刷新标定数据并根据标定类型获取需要校验的前置数据项
        self.data_checker.refresh_calibration_data()
        required_items = self.data_checker.calibration_requirements.get(calibration_type, [])
        if not required_items:
            logger.warning(f"未匹配到标定类型的前置检查项: {calibration_type}")
        
        # 检查所有必需的数据是否有效
        all_valid = True
        for item in required_items:
            if not self.data_checker.check_data_validity(item):
                all_valid = False
                break
        
        if not all_valid:
            logger.warning(f"标定数据不完整，无法开始 {calibration_type} 标定")
            return
        
        # 检查是否应该全局禁用
        should_disable, failed_conditions = self.data_checker.should_disable_all_calibration()
        if should_disable:
            logger.warning(f"标定功能被全局禁用，失败条件: {failed_conditions}")
            return
        
        logger.info(f"开始 {calibration_type} 标定: {calibration_key}")

        # 打开标定动作窗口（传入当前标定键与动作回调）
        try:
            # 若已有窗口实例，先关闭旧窗口以避免多个重复窗口
            if self.calibration_action_window:
                try:
                    self.calibration_action_window.close()
                except Exception:
                    pass
                self.calibration_action_window = None

            # 构造并显示新窗口（设置父窗口为当前标定控件，继承样式与语言）
            # 说明：作为子控件传入父级可确保继承 MainWindow 应用的 QSS 样式，
            # 同时在 CalibrationActionWindow 内部已设置 Qt.Dialog 与应用模态、系统装饰等属性。
            self.calibration_action_window = CalibrationActionWindow(
                calibration_type=calibration_type,
                calibration_key=calibration_key,
                on_action=self._on_calibration_action_clicked,
                vehicle_connection_manager=self.vehicle_connection_manager,
                parent=self
            )
            # 显示并激活窗口（确保在应用前台可见与可交互）
            self.calibration_action_window.show()
            try:
                self.calibration_action_window.raise_()
                self.calibration_action_window.activateWindow()
            except Exception:
                pass
            logger.info(f"已打开标定动作窗口: key={calibration_key}")

            # 标定命令启动逻辑已迁移至 CalibrationActionWindow 内部
        except Exception as exc:
            logger.exception(f"打开标定动作窗口失败: {exc}")

        # 发送标定开始信号（供上层流程使用）
        self.calibration_started.emit(calibration_key)

    def _on_calibration_action_clicked(self, calibration_key: str, action: str) -> None:
        """标定动作窗口按钮回调
        参数：
        - calibration_key: 当前标定项键（如 calibration_menu_laser_joint）
        - action: 动作类型（download_log / download_pcd / show_pcd）
        """
        try:
            logger.info(f"标定动作请求: key={calibration_key}, action={action}")
            # 在此处可根据 action 分发到具体业务逻辑
            # 目前仅记录日志与保留扩展点，避免阻塞UI
            # 示例：
            # if action == CalibrationActionWindow.ACTION_DOWNLOAD_LOG:
            #     self._start_download_log(calibration_key)
            # elif action == CalibrationActionWindow.ACTION_DOWNLOAD_PCD:
            #     self._start_download_pcd(calibration_key)
            # elif action == CalibrationActionWindow.ACTION_SHOW_PCD:
            #     self._show_pcd_viewer(calibration_key)
        except Exception as exc:
            logger.exception(f"处理标定动作失败: key={calibration_key}, action={action}, err={exc}")
    
    def _cancel_pending_system_check(self):
        """取消待处理的系统检测任务"""
        if hasattr(self, '_delayed_system_check_timer') and self._delayed_system_check_timer:
            logger.info("[CalibrationWidget] 取消待处理的系统检测任务")
            self._delayed_system_check_timer.stop()
            self._delayed_system_check_timer = None
    
    def _start_connection_verification(self):
        """启动连接状态确认流程"""
        logger.info("[CalibrationWidget] 开始连接状态确认流程")
        
        # 添加短暂延迟，确保连接状态完全稳定
        # 使用QTimer.singleShot避免阻塞UI线程
        QTimer.singleShot(100, self._verify_connection_and_open_dialog)
    
    def _verify_connection_and_open_dialog(self):
        """验证连接状态并打开对话框"""
        logger.info("[CalibrationWidget] 开始验证连接状态")
        
        # 详细调试信息
        logger.info(f"[CalibrationWidget] vehicle_connection_manager 存在: {self.vehicle_connection_manager is not None}")
        
        if self.vehicle_connection_manager:
            # 检查 _client_car_thread
            client_thread = getattr(self.vehicle_connection_manager, '_client_car_thread', None)
            logger.info(f"[CalibrationWidget] _client_car_thread 存在: {client_thread is not None}")
            
            if client_thread:
                # 检查线程是否运行 - 使用正确的方法名
                try:
                    is_running = hasattr(client_thread, 'isRunning') and client_thread.isRunning()
                    logger.info(f"[CalibrationWidget] _client_car_thread 正在运行: {is_running}")
                except Exception as e:
                    logger.error(f"[CalibrationWidget] 检查线程运行状态异常: {e}")
                
                # 检查 ssh_client
                ssh_client = getattr(client_thread, 'ssh_client', None)
                logger.info(f"[CalibrationWidget] ssh_client 存在: {ssh_client is not None}")
                
                if ssh_client:
                    try:
                        is_alive = ssh_client.is_connection_alive()
                        logger.info(f"[CalibrationWidget] ssh_client.is_connection_alive(): {is_alive}")
                    except Exception as e:
                        logger.error(f"[CalibrationWidget] ssh_client.is_connection_alive() 异常: {e}")
        
        # 调用 is_connected 方法
        is_connected = self.vehicle_connection_manager.is_connected()
        logger.info(f"[CalibrationWidget] vehicle_connection_manager.is_connected(): {is_connected}")
        
        if is_connected:
            logger.info("[CalibrationWidget] 车辆已连接，直接打开检测窗口")
            self._open_system_check_dialog_safely()
        else:
            logger.warning("[CalibrationWidget] 车辆未连接，无法打开检测窗口")
    
    def _handle_connection_lost(self):
        """处理连接丢失"""
        logger.info("[CalibrationWidget] 处理连接丢失事件")
        
        # 关闭现有的系统检测对话框
        if hasattr(self, 'system_check_dialog') and self.system_check_dialog:
            logger.info("[CalibrationWidget] 关闭现有的系统检测对话框")
            self.system_check_dialog.close()
            self.system_check_dialog = None

        # 兜底：确保车辆连接按钮状态重置为“连接”
        # 说明：正常情况下VehicleConnectionManager会重置按钮；
        # 若因信号路径差异未生效，这里进行兜底重置，避免UI卡在“断开”状态。
        try:
            if hasattr(self, 'connect_button') and self.connect_button:
                self.connect_button.disconnected()
                logger.info("[CalibrationWidget] 连接按钮状态已重置为‘连接’")
        except Exception as exc:
            logger.warning(f"[CalibrationWidget] 重置连接按钮状态失败: {exc}")
    
    def _update_calibration_buttons_state(self):
        """更新标定按钮状态"""
        if self.current_calibration_item:
            logger.info(f"[CalibrationWidget] 更新标定项 {self.current_calibration_item} 的按钮状态")
            self.update_detection_items_for_calibration(self.current_calibration_item)
    
    def _open_system_check_dialog_safely(self):
        """安全地打开系统检测对话框，包含错误处理和回退机制"""
        logger.info("[CalibrationWidget] 安全地打开系统检测对话框")
        
        try:
            # 1. 验证连接状态
            if not self.vehicle_connection_manager.is_connected():
                error_msg = "车辆未连接，无法开始系统检测"
                logger.warning(f"[CalibrationWidget] {error_msg}")
                from PySide2.QtWidgets import QMessageBox
                QMessageBox.warning(self, "连接错误", error_msg)
                return False
            
            # 2. 获取IP地址
            ip_address = self.vehicle_connection_manager.get_connection_ip()
            if not ip_address:
                error_msg = "无法获取车辆IP地址"
                logger.error(f"[CalibrationWidget] {error_msg}")
                from PySide2.QtWidgets import QMessageBox
                QMessageBox.critical(self, "配置错误", error_msg)
                return False
            
            # 3. 验证连接稳定性
            connection_manager = getattr(self.vehicle_connection_manager, '_connection_manager', None)
            if connection_manager and hasattr(connection_manager, 'is_stable_connection'):
                if not connection_manager.is_stable_connection():
                    error_msg = "连接不稳定，请等待连接稳定后再试"
                    logger.warning(f"[CalibrationWidget] {error_msg}")
                    from PySide2.QtWidgets import QMessageBox
                    QMessageBox.warning(self, "连接不稳定", error_msg)
                    return False
            
            # 4. 调用原始的打开方法
            self.open_system_check_dialog()
            return True
            
        except Exception as e:
            error_msg = f"打开系统检测对话框时发生错误: {str(e)}"
            logger.error(f"[CalibrationWidget] {error_msg}")
            from PySide2.QtWidgets import QMessageBox
            QMessageBox.critical(self, "系统错误", f"无法打开系统检测窗口:\n{str(e)}")
            
            # 清理可能的残留状态
            if hasattr(self, 'system_check_dialog') and self.system_check_dialog:
                try:
                    self.system_check_dialog.close()
                except:
                    pass
                self.system_check_dialog = None
            
            return False
    
    def _delayed_open_system_check_dialog(self):
        """延迟打开系统检测对话框 - 保留兼容性"""
        logger.info("[CalibrationWidget] 延迟任务执行（兼容性方法）")
        self._open_system_check_dialog_safely()
    
    def open_system_check_dialog(self):
        """打开系统检测对话框，包含完善的错误处理"""
        try:
            logger.info("[CalibrationWidget] 开始打开系统检测对话框")
            
            # 1. 获取当前连接的IP地址
            ip_address = None
            if hasattr(self, 'ip_combo') and self.ip_combo:
                ip_text = self.ip_combo.currentText().strip()
                # 提取IP地址（去除设备名称部分）
                if '(' in ip_text and ')' in ip_text:
                    ip_address = ip_text.split('(')[0].strip()
                else:
                    ip_address = ip_text
            
            if not ip_address:
                error_msg = "无法获取IP地址，请检查网络连接"
                logger.warning(f"[CalibrationWidget] {error_msg}")
                from PySide2.QtWidgets import QMessageBox
                QMessageBox.warning(self, "连接错误", error_msg)
                return
            
            # 2. 关闭已存在的对话框
            if self.system_check_dialog:
                logger.info("[CalibrationWidget] 关闭现有的系统检测窗口")
                try:
                    self.system_check_dialog.close()
                except Exception as e:
                    logger.warning(f"[CalibrationWidget] 关闭旧对话框时出错: {e}")
                finally:
                    self.system_check_dialog = None
            
            # 3. 创建新的系统检测对话框
            logger.info(f"[CalibrationWidget] 创建SystemCheckDialog，目标IP: {ip_address}")
            self.system_check_dialog = SystemCheckDialog(ip_address, self, self.vehicle_connection_manager)
            
            # 4. 连接检测完成信号
            logger.info(f"[CalibrationWidget] 检查系统检测对话框信号: {hasattr(self.system_check_dialog, 'check_completed')}")
            if hasattr(self.system_check_dialog, 'check_completed'):
                try:
                    self.system_check_dialog.check_completed.connect(self.on_system_check_completed)
                    logger.info("[CalibrationWidget] check_completed信号连接成功")
                except Exception as e:
                    logger.error(f"[CalibrationWidget] 信号连接失败: {e}")
            else:
                logger.warning("[CalibrationWidget] 系统检测对话框缺少check_completed信号")
                # 尝试直接连接信号（备用方案）
                try:
                    self.system_check_dialog.check_completed.connect(self.on_system_check_completed)
                    logger.info("[CalibrationWidget] 备用信号连接成功")
                except Exception as e:
                    logger.error(f"[CalibrationWidget] 备用信号连接也失败: {e}")
            
            # 5. 显示对话框
            self.system_check_dialog.show()
            logger.info("[CalibrationWidget] 系统检测对话框已显示")
            
            # 6. 自动开始检测
            if hasattr(self.system_check_dialog, 'start_system_check'):
                self.system_check_dialog.start_system_check()
                logger.info("[CalibrationWidget] 系统检测已开始")
            else:
                logger.warning("[CalibrationWidget] 系统检测对话框缺少start_system_check方法")
                
        except ImportError as e:
            error_msg = f"无法导入系统检测模块: {str(e)}"
            logger.error(f"[CalibrationWidget] {error_msg}")
            from PySide2.QtWidgets import QMessageBox
            QMessageBox.critical(self, "模块错误", f"系统检测功能不可用:\n{error_msg}")
            
        except Exception as e:
            error_msg = f"创建系统检测对话框时发生错误: {str(e)}"
            logger.error(f"[CalibrationWidget] {error_msg}")
            from PySide2.QtWidgets import QMessageBox
            QMessageBox.critical(self, "系统错误", f"无法打开系统检测窗口:\n{str(e)}")
            
            # 清理可能的残留状态
            if hasattr(self, 'system_check_dialog'):
                self.system_check_dialog = None
            
            logger.info(f"[CalibrationWidget] 已打开系统检测窗口，目标IP: {ip_address}")
            
        except Exception as e:
            logger.error(f"[CalibrationWidget] 打开系统检测窗口失败: {e}")
    
    def on_system_check_completed(self, results):
        """系统检测完成处理 - 增强调试日志"""
        logger.info(f"[CalibrationWidget] 系统检测完成，结果已保存到全局参数: {results}")
        
        # 刷新标定数据检查器的数据，确保使用最新的检测结果
        if hasattr(self, 'data_checker') and self.data_checker:
            try:
                refresh_success = self.data_checker.refresh_calibration_data()
                if refresh_success:
                    logger.info("[CalibrationWidget] 标定数据检查器数据刷新成功")
                else:
                    logger.warning("[CalibrationWidget] 标定数据检查器数据刷新失败")
            except Exception as e:
                logger.error(f"[CalibrationWidget] 刷新标定数据检查器数据时出错: {e}")
        
        # 如果当前有选中的标定项，重新更新检测项显示
        if hasattr(self, 'current_calibration_item') and self.current_calibration_item:
            logger.info(f"[CalibrationWidget] 重新更新标定项检测显示: {self.current_calibration_item}")
            self.update_detection_items_for_calibration(self.current_calibration_item)
        else:
            logger.info("[CalibrationWidget] 没有当前选中的标定项，跳过检测项更新")
    
    def closeEvent(self, event):
        """窗口关闭事件"""
        # 关闭系统检测对话框
        if self.system_check_dialog:
            self.system_check_dialog.close()
            self.system_check_dialog = None
            
        logger.info("车辆标定窗口关闭")
        super().closeEvent(event)